import json
from time import strptime, mktime
from PyQt5.QtGui import QTextDocument, QTextCursor
from PyQt5.QtPrintSupport import QPrintPreviewDialog

data = []
data_filter = ""
text_filter = ''
mode = ''


def init() -> [list, list]:
    type_data = []
    log_data = []
    try:
        with open('typeData.json', 'r') as f:
            type_data = json.load(f)
        with open('logData.json', 'r') as f:
            log_data = json.load(f)
    except IOError as err:
        print('IOError: {0}'.format(err))
    except json.JSONDecodeError as err:
        print("JSONDecoderError: {0}".format(err))
    return [type_data, log_data]


def date_checker(date: str, no_today: bool, strict_mode: bool = False) -> bool:
    flag = False
    global data_filter
    date_stamp = mktime(strptime(date, '%Y/%m/%d'))
    filter_stamp = mktime(strptime(data_filter, '%Y/%m/%d'))
    if strict_mode:
        if date_stamp == filter_stamp:
            flag = True
    else:
        if no_today:
            filter_stamp -= 60 * 60 * 24
        if date_stamp <= filter_stamp:
            flag = True
    return flag


def data_checker(kind: str) -> bool:
    global text_filter
    return kind == text_filter


def get_print_data(data_old: list, mode_: str, no_today: bool = False) -> list:
    global data_filter
    new_data = []
    if mode_ == '入库模式':
        for item in data_old[1]:
            if item['mode'] == 1 and (data_filter == '' or date_checker(item['date'], no_today, True)):
                new_data.append(item)
        new_data = clean_up(new_data)
    elif mode_ == '出库模式':
        for item in data_old[1]:
            if item['mode'] == -1 and (data_filter == '' or date_checker(item['date'], no_today, True)):
                new_data.append(item)
        new_data = clean_up(new_data)
    elif mode_ == '结余模式':
        data_out = []
        data_in = []
        for item in data_old[1]:
            if item['mode'] == -1 and date_checker(item['date'], no_today=no_today):
                data_out.append(item)
            elif item['mode'] == 1 and item['number'] != 0 and date_checker(item['date'], no_today=no_today):
                data_in.append(item)
        data_out = clean_up(data_out)
        data_in = clean_up(data_in)
        for item in data_in:
            for index in range(len(data_out)):
                try:
                    _ = data_out[index]['is_removed']
                except KeyError:
                    if item['kind'] == data_out[index]['kind'] and item['unitPrice'] == data_out[index]['unitPrice']:
                        item['number'] -= data_out[index]['number']
                        data_out[index]['is_removed'] = True
            if item['number'] != 0:
                new_data.append(item)
    return new_data


def get_summary() -> [float, float, float]:
    global data
    total_number = float(0)
    total_price = float(0)
    for item in data:
        total_number += item['number']
        total_price += item['number'] * item['unitPrice']
    try:
        average_unit_price = total_price / total_number
    except ZeroDivisionError as err:
        print("ZeroDivisionError: {0}".format(err))
        average_unit_price = float(0)
    return [total_number, average_unit_price, total_price]


def paint_request_handler(printer):
    doc = QTextDocument()
    cursor = QTextCursor(doc)
    global data, mode
    data = get_print_data(init(), mode)
    string = '<table border="1" style="font-size:13px;">'
    try:
        if mode == '出库模式' or mode == '入库模式':
            string += '<tr style="font-size:20px;"><th colspan="7" align="center">'
            if mode == '出库模式':
                string += '食堂物资领料出库单'
            if mode == '入库模式':
                string += '食堂物资入库单'
            string += '</th></tr><tr><th>序号</th><th width="80">物资名称</th><th>数量</th><th>单价</th><th>金额</th><th>日期</th>'
            if mode == '出库模式':
                string += '<th>领用人</th>'
            else:
                string += '<th>备注</th>'
            string += '</tr>'
            count = 0
            data = clean_up(data, enable_filter=True)
            for log in data:
                count += 1
                string += '<tr>'
                string += '<td>%d</td>' % count + \
                          '<td>' + log['kind'] + '</td><td>' + ('%.2f' % log['number']) + '(' + log['unit'] + ')'
                string += ('</td><td>%.2f元</td><td>' % log['unitPrice']) + ('%.2f' % (log['number'] * log['unitPrice']))
                string += '</td><td>%s</td>' % log['date']
                string += '</tr>'
            summary = get_summary()
            string += '<tr><td>无</td><td>本日合计</td><td>%.2f</td><td>%.2f元</td><td>%.2f</td></tr>' \
                      % (summary[0], summary[1], summary[2])
            string += '<tr><td>无</td><td colspan="3">审核人签字:</td><td colspan="3">制表人签字:</td></tr>'
        else:
            if mode == '结余模式':
                string += '<tr style="font-size:20px;"><th colspan="15">食堂菜品（日）出入存情况表</th></tr>'
                string += '<tr align="center" ><th rowspan="2">序号</th><th width="80" rowspan="2">物资名称</th>'
                string += '<th colspan="3">上日库存</th><th colspan="3">本日入库</th><th colspan="3">本日出库</th><th ' \
                          'colspan="3">本日库存</th><th rowspan="2">备注</th></tr>'
                string += '<tr>' + '<th>数量</th><th>单价</th><th>金额</th>' * 4 + '</tr>'
                global data_filter
                if data_filter != '':
                    data_in = get_print_data(init(), "入库模式")
                    data_out = get_print_data(init(), "出库模式")
                    data_out_summary = get_print_data(init(), "结余模式", no_today=True)
                    count = 0
                    data_out = clean_up(data_out, enable_filter=True)
                    data_in = clean_up(data_in, enable_filter=True)
                    data_out_summary = clean_up(data_out_summary, enable_filter=True)
                    data = clean_up(data, enable_filter=True)
                    for item in data_out_summary:
                        count += 1
                        string += '<tr>' + '<td>%d</td>' % count + '<td>%s</td>' % item[
                            'kind'] + '<td>%.2f(%s)</td>' % (item['number'], item['unit']) + '<td>%.2f</td>' % item[
                                      'unitPrice'] + '<td>%.2f</td>' % (item['unitPrice'] * item['number'])
                        flag = False
                        for i in data_in:
                            if i['kind'] == item['kind'] and i['unitPrice'] == item['unitPrice'] and i['mode'] == 1:
                                string += '<td>%.2f(%s)</td>' % (i['number'], i['unit']) + '<td>%.2f</td>' % i[
                                    'unitPrice'] + '<td>%.2f</td>' % (i['unitPrice'] * i['number'])
                                data_in.remove(i)
                                flag = True
                        if not flag:
                            string += '<td>0.00</td><td>0.00</td><td>0.00</td>'
                        flag = False
                        for i in data_out:
                            if i['kind'] == item['kind'] and i['unitPrice'] == item['unitPrice'] and i['mode'] == -1:
                                string += '<td>%.2f(%s)</td>' % (i['number'], i['unit']) + '<td>%.2f</td>' % i[
                                    'unitPrice'] + '<td>%.2f</td>' % (i['unitPrice'] * i['number'])
                                data_out.remove(i)
                                flag = True
                        if not flag:
                            string += '<td>0.00</td><td>0.00</td><td>0.00</td>'
                        flag = False
                        for i in data:
                            if i['kind'] == item['kind'] and i['unitPrice'] == item['unitPrice']:
                                string += '<td>%.2f(%s)</td>' % (i['number'], i['unit']) + '<td>%.2f</td>' % i[
                                    'unitPrice'] + '<td>%.2f</td>' % (i['unitPrice'] * i['number'])
                                flag = True
                        if not flag:
                            string += '<td>0.00</td><td>0.00</td><td>0.00</td>'
                        string += '</tr>'
                    for item in data_in:
                        count += 1
                        string += '<tr>' + '<td>%d</td>' % count + '<td>%s</td>' % item[
                            'kind'] + '<td>0.00</td><td>0.00</td><td>0.00</td>' + '<td>%.2f(%s)</td>' % (
                                      item['number'], item['unit']) + '<td>%.2f</td>' % item[
                                      'unitPrice'] + '<td>%.2f</td>' % (
                                          item['unitPrice'] * item['number'])
                        flag = False
                        for i in data_out:
                            if i['kind'] == item['kind'] and i['unitPrice'] == item['unitPrice'] and i['mode'] == -1:
                                string += '<td>%.2f(%s)</td>' % (i['number'], i['unit']) + '<td>%.2f</td>' % i[
                                    'unitPrice'] + '<td>%.2f</td>' % (i['unitPrice'] * i['number'])
                                data_out.remove(i)
                                flag = True
                        if not flag:
                            string += '<td>0.00</td><td>0.00</td><td>0.00</td>'
                        flag = False
                        for i in data:
                            if i['kind'] == item['kind'] and i['unitPrice'] == item['unitPrice']:
                                string += '<td>%.2f(%s)</td>' % (i['number'], i['unit']) + '<td>%.2f</td>' % i[
                                    'unitPrice'] + '<td>%.2f</td>' % (i['unitPrice'] * i['number'])
                                data.remove(i)
                                flag = True
                        if not flag:
                            string += '<td>0.00</td><td>0.00</td><td>0.00</td>'
                        string += '</tr>'
                    string += '<tr><td colspan="7">审核人签字:</td><td colspan="7">制表人签字:</td></tr>'

    except IndexError as err:
        print('IndexError: {0}'.format(err))
    string += '</table>'
    cursor.insertHtml(string)
    doc.print_(printer)


def clean_up(data_in: list, enable_filter: bool = False) -> list:
    data_out = data_in
    to_remove = []
    for index in range(len(data_out)):
        try:
            _ = data_out[index]['to_remove']
            continue
        except KeyError:
            for i in range(index + 1, len(data_out)):
                try:
                    _ = data_out[i]['to_remove']
                    continue
                except KeyError:
                    if data_out[i]['kind'] == data_out[index]['kind'] and \
                            data_out[i]['unitPrice'] == data_out[index]['unitPrice']:
                        data_out[index]['number'] += data_out[i]['number']
                        data_out[i]['to_remove'] = True
                        to_remove.append(i)
    to_remove.sort(reverse=True)
    for idx in to_remove:
        data_out.pop(idx)
    to_remove = []
    for index in range(len(data_out)):
        if text_filter in data_out[index]['kind'] or (not enable_filter) or text_filter == '':
            continue
        to_remove.append(index)
    to_remove.sort(reverse=True)
    for idx in to_remove:
        data_out.pop(idx)
    return data_out


class PrinterUi:
    @staticmethod
    def print_now():
        global data, data_filter, mode
        # mode = self.selections[self.comboBox.currentIndex()]
        # data_filter = self.dateEdit.date().toString('yyyy/MM/dd')
        data_full = init()
        data = get_print_data(data_full, mode)
        pp = QPrintPreviewDialog()
        # noinspection PyUnresolvedReferences
        pp.paintRequested.connect(paint_request_handler)
        pp.exec_()
